package com.thesis.manage.service.impl;

import com.thesis.manage.common.constant.YesOrNoEnum;
import com.thesis.manage.common.exception.CommonException;
import com.thesis.manage.common.mongodb.impl.AbstractMongoServiceImpl;
import com.thesis.manage.common.utils.Result;
import com.thesis.manage.domain.Teacher;
import com.thesis.manage.domain.Thesis;
import com.thesis.manage.domain.Time;
import com.thesis.manage.service.StudentThesisService;
import com.thesis.manage.service.TeacherService;
import com.thesis.manage.service.ThesisService;
import com.thesis.manage.service.TimeService;
import com.thesis.manage.service.constant.ErrorMessage;
import com.thesis.manage.service.model.*;
import com.thesis.manage.service.module.vo.ThesisVO;
import com.thesis.manage.service.module.vo.TimeVO;
import com.thesis.manage.service.utils.TimeFormat;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.*;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author php
 * @date 2018/2/3
 */
@Service
public class ThesisServiceImpl extends AbstractMongoServiceImpl<Thesis> implements ThesisService {
    @Resource
    private TimeService timeService;

    @Resource
    private MongoTemplate mongoTemplate;

    @Resource
    private TeacherService teacherService;

    @Resource
    private StudentThesisService studentThesisService;

    @Override
    protected Class<Thesis> getEntityClass() {
        return Thesis.class;
    }

    @Override
    public Result checkOpenApplication(Integer type) {
        Time time = this.timeService.findByType(type);
        TimeVO timeVO = new TimeVO();
        if (time == null) {
            timeVO.setType(AnswerStateEnum.NO_OPEN.getValue());
            return Result.ok(timeVO);
        } else {
            List<Date> dates = TimeFormat.formatDate(time.getTimeSlot());
            if (CollectionUtils.isNotEmpty(dates)) {
                long start = dates.get(0).getTime();
                long end = dates.get(1).getTime();
                timeVO.setBegin(dates.get(0));
                timeVO.setEnd(dates.get(1));
                long current = System.currentTimeMillis();
                if (current < start) {
                    timeVO.setType(AnswerStateEnum.NO_OPEN.getValue());
                    return Result.ok(timeVO);
                }
                if (current > end) {
                    timeVO.setType(AnswerStateEnum.END.getValue());
                    return Result.ok(timeVO);
                }
            } else {
                timeVO.setType(AnswerStateEnum.NO_OPEN.getValue());
                return Result.ok(timeVO);
            }
        }
        timeVO.setType(AnswerStateEnum.RUNNING.getValue());
        return Result.ok(timeVO);
    }

    @Override
    public void save(Thesis thesis) {
        //时间验证
        Result result = this.checkOpenApplication(TimeTypeEnum.APPLY.getValue());
        TimeVO timeVO = (TimeVO) result.getData();
        if (timeVO.getType().intValue() == AnswerStateEnum.NO_OPEN.getValue()) {
            throw new CommonException("no open", "申请未开启");
        }
        if (timeVO.getType().intValue() == AnswerStateEnum.END.getValue()) {
            throw new CommonException("end", "申请已结束");
        }
        Assert.notNull(thesis, ErrorMessage.OBJECT_NO_INSTANCE);
        Thesis one = this.findByName(thesis.getName());
        if (one != null) {
            throw new CommonException("apply thesis failed", ErrorMessage.DATA_ALREADY_EXIST);
        }
        this.insert(thesis);
    }

    @Override
    public Page<ThesisVO> findByTeacher(Thesis thesis, Pageable pageable) {
        List<ThesisVO> thesisVOS = new ArrayList<>();
        Page<Thesis> page = this.findByPage(thesis, pageable, null);
        try {
            if (CollectionUtils.isNotEmpty(page.getContent())) {
                ThesisVO thesisVO;
                for (Thesis t : page.getContent()) {
                    thesisVO = new ThesisVO();
                    thesisVO.setId(t.getId());
                    thesisVO.setName(t.getName());
                    thesisVO.setDate(t.getStartTime());
                    thesisVO.setStatus(ExamineEnum.getName(t.getStatus()));
                    thesisVO.setType(ThesisTypeEnum.getName(t.getType()));
                    thesisVOS.add(thesisVO);
                }
                PageRequest request = new PageRequest(pageable.getPageNumber() - 1, pageable.getPageSize());
                return new PageImpl<>(thesisVOS, request, page.getTotalElements());
            }
        } catch (Exception e) {
            throw new CommonException("data covert failed", "论题信息转换失败");
        }
        return null;
    }

    @Override
    public Page<ThesisVO> reviewList(Thesis thesis, Pageable pageable) {
        List<ThesisVO> thesisVOS = new ArrayList<>();
        Page<Thesis> page = this.findByPage(thesis, pageable, null);
        try {
            if (CollectionUtils.isNotEmpty(page.getContent())) {
                ThesisVO thesisVO;
                for (Thesis t : page.getContent()) {
                    thesisVO = new ThesisVO();
                    thesisVO.setId(t.getId());
                    thesisVO.setName(t.getName());
                    thesisVO.setDate(t.getStartTime());
                    thesisVO.setType(ThesisTypeEnum.getName(t.getType()));
                    thesisVO.setPerson(t.getPerson());
                    thesisVO.setPersonType(RoleEnum.getName(t.getPersonType()));
                    thesisVOS.add(thesisVO);
                }
                PageRequest request = new PageRequest(pageable.getPageNumber() - 1, pageable.getPageSize());
                return new PageImpl<>(thesisVOS, request, page.getTotalElements());
            }
        } catch (Exception e) {
            throw new CommonException("data covert failed", "论题信息转换失败");
        }
        return null;
    }

    @Override
    public Page<ThesisVO> findAllByCollege(Thesis thesis, Pageable pageable) {
        List<ThesisVO> thesisVOS = new ArrayList<>();
        Page<Thesis> page = this.findByPage(thesis, pageable, null);
        try {
            if (CollectionUtils.isNotEmpty(page.getContent())) {
                ThesisVO thesisVO;
                for (Thesis t : page.getContent()) {
                    thesisVO = new ThesisVO();
                    thesisVO.setId(t.getId());
                    thesisVO.setName(t.getName());
                    thesisVO.setDate(t.getStartTime());
                    thesisVO.setType(ThesisTypeEnum.getName(t.getType()));
                    thesisVOS.add(thesisVO);
                }
                PageRequest request = new PageRequest(pageable.getPageNumber() - 1, pageable.getPageSize());
                return new PageImpl<>(thesisVOS, request, page.getTotalElements());
            }
        } catch (Exception e) {
            throw new CommonException("data covert failed", "论题信息转换失败");
        }
        return null;
    }

    @Override
    public void adopt(Long id, String message) {
        Thesis thesis = this.findById(id);
        Assert.notNull(thesis, ErrorMessage.DATA_NO_EXIST);
        thesis = new Thesis();
        thesis.setId(id);
        //审核通过
        thesis.setStatus(ExamineEnum.EXAMINE_SUCCESS.getValue());
        if (StringUtils.isNotBlank(message)) {
            thesis.setMessage(message);
        }
        this.update(thesis);
    }

    @Override
    public void unAdopt(Long id, String message) {
        Assert.notNull(message, "请填写未通过的原因!");
        Thesis thesis = new Thesis();
        thesis.setId(id);
        thesis.setStatus(ExamineEnum.EXAMINE_FAILED.getValue());
        thesis.setMessage(message);
        this.update(thesis);
    }

    @Override
    public List<ThesisVO> findAllByPerson(Thesis thesis) {
        ArrayList<ThesisVO> result = new ArrayList<>();
        Query query = new Query();
        query.addCriteria(Criteria.where("personId").is(thesis.getPersonId()));
        query.addCriteria(Criteria.where("delStatus").is(YesOrNoEnum.NO.getValue()));
        List<Thesis> theses = this.mongoTemplate.find(query, getEntityClass());
        if (CollectionUtils.isNotEmpty(theses)) {
            ThesisVO thesisVO;
            for (Thesis t : theses) {
                thesisVO = new ThesisVO();
                thesisVO.setId(t.getId());
                thesisVO.setName(t.getName());
                thesisVO.setDate(t.getStartTime());
                thesisVO.setType(ThesisTypeEnum.getName(t.getType()));
                thesisVO.setStatus(ExamineEnum.getName(t.getStatus()));
                result.add(thesisVO);
            }
        }
        return result;
    }

    @Override
    public Page<ThesisVO> showThesisList(String teacherNumber, Long studentId, Pageable pageable) {
        if (pageable == null) {
            throw new CommonException("pageable.is.null", "pageable不能为空");
        }
        List<ThesisVO> thesisVOS = new ArrayList<>();
        //通过教师编号查询老师
        Teacher teacher = this.teacherService.findByTeacherNumber(teacherNumber);
        Query query = new Query();
        query.addCriteria(Criteria.where("personId").in(studentId, teacher.getId()));
        query.addCriteria(Criteria.where("delStatus").is(YesOrNoEnum.NO.getValue()));
        query.addCriteria(Criteria.where("status").is(ExamineEnum.EXAMINE_SUCCESS.getValue()));
        PageRequest pageRequest;
        if (pageable.getSort() == null) {
            pageRequest = new PageRequest(pageable.getPageNumber() - 1, pageable.getPageSize(), new Sort(Sort.Direction.DESC, "startTime"));
            query.with(pageRequest);
        } else {
            pageRequest = new PageRequest(pageable.getPageNumber() - 1, pageable.getPageSize(), pageable.getSort());
            query.with(pageRequest);
        }
        long count = this.mongoTemplate.count(query, getEntityClass());
        List<Thesis> list = this.mongoTemplate.find(query, getEntityClass());
        PageImpl<Thesis> page = new PageImpl<>(list, pageRequest, count);
        try {
            if (CollectionUtils.isNotEmpty(page.getContent())) {
                ThesisVO thesisVO;
                for (Thesis t : page.getContent()) {
                    Boolean exist = this.studentThesisService.exist(t.getId());
                    thesisVO = new ThesisVO();
                    thesisVO.setStatus(exist ? YesOrNoEnum.NO.getValue().toString() : YesOrNoEnum.YES.getValue().toString());
                    thesisVO.setDate(t.getStartTime());
                    thesisVO.setType(ThesisTypeEnum.getName(t.getType()));
                    thesisVO.setId(t.getId());
                    thesisVO.setName(t.getName());
                    thesisVOS.add(thesisVO);
                }
                return new PageImpl<>(thesisVOS, pageRequest, page.getTotalElements());
            }
        } catch (Exception e) {
            throw new CommonException("data covert failed", "论题信息转换失败");
        }
        return null;
    }


    private Thesis findByName(String name) {
        Assert.notNull(name, ErrorMessage.PARAMS_IS_NULL);
        Thesis thesis = new Thesis();
        thesis.setName(name);
        return this.findByOne(thesis);
    }
}
